02 自定义手写签名控件 发表于 2020-01-02 | 分类于 Custom View | 自定义 View123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import java.util.LinkedList;public class PaintView extends View { /** * 存储所有的线条 */ private LinkedList<LinkedList<FPoint>> mLines; /** * 存储撤回的线条 */ private LinkedList<LinkedList<FPoint>> mRecyles; private Paint mPaintLine; private boolean isTouching; public PaintView(Context context, AttributeSet attrs) { super(context, attrs); // 设定画笔 mPaintLine = new Paint(); mPaintLine.setColor(Color.GREEN); mPaintLine.setStrokeWidth(4); // 建构线条数据结构对象 mLines = new LinkedList<>(); mRecyles = new LinkedList<>(); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { // 离开屏幕 isTouching = false; } else { LinkedList<FPoint> line; // 触摸开始 if (!isTouching) { line = new LinkedList<>(); mLines.add(line); isTouching = true; } else { // 开始滑动 line = mLines.getLast(); } line.add(new FPoint(event.getX(), event.getY())); postInvalidate(); } return true; } @Override protected void onDraw(Canvas canvas) { for (LinkedList<FPoint> line : mLines) { if (line.size() > 1) { // 至少两个点才能画一条线 for (int i = 1; i < line.size(); i++) { FPoint p1 = line.get(i - 1); FPoint p2 = line.get(i); canvas.drawLine(p1.x, p1.y, p2.x, p2.y, mPaintLine); } } } } public void clear() { if (mLines != null) { mLines.clear(); postInvalidate(); } } public void undo() { if (mLines != null && mLines.size() > 0 && mRecyles != null) { mRecyles.add(mLines.removeLast()); postInvalidate(); } } public void redo() { if (mRecyles != null && mRecyles.size() > 0 && mLines != null) { mLines.add(mRecyles.removeLast()); postInvalidate(); } } private class FPoint { private float x, y; private FPoint(float x, float y) { this.x = x; this.y = y; } }} 界面操作代码12345678910111213141516171819202122232425262728public class DemoActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.act_demo); final PaintView paintView = findViewById(R.id.paint_view); findViewById(R.id.clear).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { paintView.clear(); } }); findViewById(R.id.undo).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { paintView.undo(); } }); findViewById(R.id.redo).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { paintView.redo(); } }); }} 界面布局12345678910111213141516171819202122232425262728293031323334353637<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFF" android:orientation="vertical"> <com.xxt.xtest.PaintView android:id="@+id/paint_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal"> <Button android:id="@+id/clear" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="Clear"/> <Button android:id="@+id/undo" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="Undo"/> <Button android:id="@+id/redo" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="Redo"/> </LinearLayout></LinearLayout>